/*
 RTSP definitions
 Copyright (c) 2002 Fabrice Bellard

This file is part of FFmpeg.

FFmpeg is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

FFmpeg is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with FFmpeg; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef AVFORMAT_RTSP_H
#define AVFORMAT_RTSP_H
 
#include <stdint.h>
#include "avformat.h"
#include "rtspcodes.h"
#include "rtpdec.h"
#include "network.h"
#include "httpauth.h"
 
 enum RTSPLowerTransport {
	RTSP_LOWER_TRANSPORT_UDP = 0,           
	RTSP_LOWER_TRANSPORT_TCP = 1,                              
      	RTSP_LOWER_TRANSPORT_UDP_MULTICAST = 2, 
	RTSP_LOWER_TRANSPORT_NB
 };
 
enum RTSPTransport {
    RTSP_TRANSPORT_RTP, 
    RTSP_TRANSPORT_RDT, 
    RTSP_TRANSPORT_NB
};

enum RTSPControlTransport {
    RTSP_MODE_PLAIN,   
    RTSP_MODE_TUNNEL   
};

#define RTSP_DEFAULT_PORT   554
#define RTSP_MAX_TRANSPORTS 8
#define RTSP_TCP_MAX_PACKET_SIZE 1472
#define RTSP_DEFAULT_NB_AUDIO_CHANNELS 1
#define RTSP_DEFAULT_AUDIO_SAMPLERATE 44100
#define RTSP_RTP_PORT_MIN 5000
#define RTSP_RTP_PORT_MAX 100
 
typedef struct RTSPTransportField {
    int interleaved_min, interleaved_max;
    int port_min, port_max;
 
    int client_port_min, client_port_max;
 
    int server_port_min, server_port_max;
 
    int ttl;

    struct sockaddr_storage destination; 
    char source[INET6_ADDRSTRLEN + 1]; 
    enum RTSPTransport transport;
    enum RTSPLowerTransport lower_transport;
} RTSPTransportField;

typedef struct RTSPMessageHeader {
     int content_length;
 
     enum RTSPStatusCode status_code; 
     int nb_transports;
 
     int64_t range_start, range_end;

     RTSPTransportField transports[RTSP_MAX_TRANSPORTS];
 
     int seq;                         
     char session_id[512]; 
     char location[4096];
 
     char real_challenge[64];
 
     char server[64];
 
     int timeout;
 
     int notice; 
     char reason[256];
} RTSPMessageHeader;
 
enum RTSPClientState {
   RTSP_STATE_IDLE,    
   RTSP_STATE_STREAMING, 
   RTSP_STATE_PAUSED,  
   RTSP_STATE_SEEKING, 
};

 enum RTSPServerType {
    RTSP_SERVER_RTP,  
    RTSP_SERVER_REAL, 
    RTSP_SERVER_WMS,  
    RTSP_SERVER_NB
};

typedef struct RTSPState {
    URLContext *rtsp_hd; /* RTSP TCP connection handle */

    int nb_rtsp_streams;

    struct RTSPStream **rtsp_streams; 
    enum RTSPClientState state;
 
    int64_t seek_timestamp;
 
    /* XXX: currently we use unbuffered input */
    //    ByteIOContext rtsp_gb;
 
    int seq;                          
    char session_id[512];
 
    int timeout;

    int64_t last_cmd_time;

     enum RTSPTransport transport;
 
     enum RTSPLowerTransport lower_transport;

    enum RTSPServerType server_type;

     char real_challenge[64];
 
    char auth[128];
 
     HTTPAuthState auth_state;

     char last_reply[2048]; /* XXX: allocate ? */

    void *cur_transport_priv;
 
    int need_subscription;

    enum AVDiscard *real_setup_cache;

    enum AVDiscard *real_setup;

    char last_subscription[1024];

     AVFormatContext *asf_ctx;
 
     uint64_t asf_pb_pos;

    char control_uri[1024];

   URLContext *rtsp_hd_out;

   enum RTSPControlTransport control_transport;

    /* Number of RTCP BYE packets the RTSP session has received.
     * An EOF is propagated back if nb_byes == nb_streams.
     * This is reset after a seek. */
    int nb_byes;

   uint8_t* recvbuf;

    int filter_source;

     int lower_transport_mask;
 
     uint64_t packets;

     struct pollfd *p;
 } RTSPState;

 typedef struct RTSPStream {
    URLContext *rtp_handle;   
    void *transport_priv; 
    int stream_index;
 
    int interleaved_min, interleaved_max;
 
    char control_url[1024];   
    int sdp_port;             
    struct sockaddr_storage sdp_ip; 
    int sdp_ttl;              
    int sdp_payload_type;     

     RTPDynamicProtocolHandler *dynamic_handler;
 
    PayloadContext *dynamic_protocol_context;
 } RTSPStream;

 void ff_rtsp_parse_line(RTSPMessageHeader *reply, const char *buf,
                         RTSPState *rt, const char *method);
 
 extern int rtsp_rtp_port_min;
 extern int rtsp_rtp_port_max;
 
 int ff_rtsp_send_cmd_async(AVFormatContext *s, const char *method,
                           const char *url, const char *headers);

int ff_rtsp_send_cmd_with_content(AVFormatContext *s,
                                   const char *method, const char *url,
                                  const char *headers,
                                 RTSPMessageHeader *reply,
                                   unsigned char **content_ptr,
                                  const unsigned char *send_content,
                                   int send_content_length);

int ff_rtsp_send_cmd(AVFormatContext *s, const char *method,
                     const char *url, const char *headers,
                      RTSPMessageHeader *reply, unsigned char **content_ptr);
 
 int ff_rtsp_read_reply(AVFormatContext *s, RTSPMessageHeader *reply,
                        unsigned char **content_ptr,
                        int return_on_interleaved_data, const char *method);

 void ff_rtsp_skip_packet(AVFormatContext *s);
 
 int ff_rtsp_connect(AVFormatContext *s);
 void ff_rtsp_close_streams(AVFormatContext *s);
 void ff_rtsp_close_connections(AVFormatContext *rt);
 int ff_rtsp_setup_input_streams(AVFormatContext *s, RTSPMessageHeader *reply);
 
 int ff_rtsp_setup_output_streams(AVFormatContext *s, const char *addr);
 
 int ff_sdp_parse(AVFormatContext *s, const char *content); 
int ff_rtsp_tcp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
                             uint8_t *buf, int buf_size);
 
 int ff_rtsp_fetch_packet(AVFormatContext *s, AVPacket *pkt);
 
 int ff_rtsp_make_setup_request(AVFormatContext *s, const char *host, int port,
                               int lower_transport, const char *real_challenge);
 
 void ff_rtsp_undo_setup(AVFormatContext *s);

#endif /* AVFORMAT_RTSP_H */

